package com.medvalley.tcm.service.impl;

import com.google.common.collect.Lists;
import com.medvalley.tcm.base.BusinessException;
import com.medvalley.tcm.base.Constants;
import com.medvalley.tcm.controller.admin.vo.inputvo.AdminSearchDoctorInputVo;
import com.medvalley.tcm.controller.admin.vo.outputvo.DoctorOutputVo;
import com.medvalley.tcm.controller.admin.vo.outputvo.PageDataOutputVo;
import com.medvalley.tcm.dao.DoctorDao;
import com.medvalley.tcm.domain.Doctor;
import com.medvalley.tcm.service.DoctorService;
import com.medvalley.tcm.vo.inputvo.SearchDoctorInputVo;
import com.medvalley.tcm.vo.outputvo.DoctorPageOutputVo;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author linsong
 * @date 2019/4/21 15:54
 **/
@Service
public class DoctorServiceImpl implements DoctorService {

    @Autowired
    private DoctorDao doctorDao;

    @Override
    public long save(Doctor doctor) {
        return 0;
    }

    @Override
    public Doctor updateDoctor(Doctor doctor) {
        Doctor old = doctorDao.findOneByPhone(doctor.getPhone());
        if (old != null) {
            doctor.setCredentialQualification(old.getCredentialQualification());
            doctor.setCredentialStatus(old.getCredentialStatus());
            doctorDao.save(doctor);
        }
        return doctor;
    }

    @Override
    public Doctor getById(long id) {
        return doctorDao.findById(id).orElseThrow(() -> new BusinessException("查无此人"));
    }

    @Override
    public Doctor login(String phone) {
        Doctor doctor = doctorDao.findOneByPhone(phone);
        if (doctor == null) {
            doctor = new Doctor();
            doctor.setPhone(phone);
            doctorDao.save(doctor);
        }
        return doctor;
    }

    @Override
    public void saveCredential(String phone, String url) {
        Doctor doctor = doctorDao.findOneByPhone(phone);
        doctor.setCredentialQualification(url);
        doctor.setCredentialStatus(1);//改成审核中
        doctorDao.save(doctor);
    }

    @Override
    public void setHeadIcon(String phone, String url) {
        Doctor doctor = doctorDao.findOneByPhone(phone);
        doctor.setHeadIcon(url);
        doctorDao.save(doctor);
    }

    @Override
    public void findNotCredentialDoctor(int pageNo, int pageSize, DoctorPageOutputVo doctorPageOutputVo) {
        pageNo = pageNo - 1 < 0 ? 0 : pageNo - 1;
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, Sort.Direction.DESC, "id");
        Specification<Doctor> specification = new Specification<Doctor>() {
            @Override
            public Predicate toPredicate(Root<Doctor> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Predicate predicate = criteriaBuilder.equal(root.get("credentialStatus").as(Integer.class), 1);
                return criteriaBuilder.and(predicate);
            }
        };
        Page<Doctor> pageData = doctorDao.findAll(specification, pageRequest);
        doctorPageOutputVo.setDoctors(pageData.getContent());
        doctorPageOutputVo.setTotalPage(pageData.getTotalPages());

    }

    @Override
    public void updateCredentialStatus(long id, int status) {

        Doctor doctor = doctorDao.findById(id).orElseThrow(() -> new BusinessException("查无此人"));
        doctor.setCredentialStatus(status);
        doctorDao.save(doctor);
    }

    /**
     * 病人搜索医生
     *
     * @param searchDoctorInputVo
     * @return
     */
    @Override
    public DoctorPageOutputVo searchDoctor(final SearchDoctorInputVo searchDoctorInputVo) {
        DoctorPageOutputVo doctorPageOutputVo = new DoctorPageOutputVo();
        doctorPageOutputVo.setPageNo(searchDoctorInputVo.getPageNo());

        int pageNo = searchDoctorInputVo.getPageNo();
        int pageSize = searchDoctorInputVo.getPageSize();
        pageNo = pageNo - 1 < 0 ? 0 : pageNo - 1;
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, Sort.Direction.DESC, "id");
        Specification<Doctor> specification = new Specification<Doctor>() {
            @Override
            public Predicate toPredicate(Root<Doctor> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                // 城市
                if (!StringUtils.isEmpty(searchDoctorInputVo.getCityCode())) {
                    list.add(criteriaBuilder.like(root.get("city").as(String.class), "%" + searchDoctorInputVo.getCityCode()));
                }
                // 科室
                if (searchDoctorInputVo.getDepartmentId() > 0) {
                    list.add(criteriaBuilder.equal(root.get("department").as(Integer.class), searchDoctorInputVo.getDepartmentId()));
                }
                // 职称
                if (searchDoctorInputVo.getPosition() > 0) {
                    list.add(criteriaBuilder.equal(root.get("position").as(Integer.class), searchDoctorInputVo.getPosition()));
                }
                //
                if (searchDoctorInputVo.getPrice() > 0) {
                    list.add(criteriaBuilder.le(root.get("price").as(Float.class), searchDoctorInputVo.getPrice()));
                }
                list.add(criteriaBuilder.equal(root.get("credentialStatus").as(Integer.class), 2));
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
        Page<Doctor> pageData = doctorDao.findAll(specification, pageRequest);
        doctorPageOutputVo.setDoctors(pageData.getContent());
        doctorPageOutputVo.setTotalPage(pageData.getTotalPages());
        return doctorPageOutputVo;
    }

    @Override
    public void deleteDoctor(long id) {
        doctorDao.deleteById(id);
    }

    /**
     * 管理后台搜索医生
     *
     * @param adminSearchDoctorInputVo
     * @return
     */
    @Override
    public PageDataOutputVo<DoctorOutputVo> search(AdminSearchDoctorInputVo adminSearchDoctorInputVo) {
        PageDataOutputVo<DoctorOutputVo> pageDataOutputVo = new PageDataOutputVo<>();
        int pageNo = adminSearchDoctorInputVo.getPageNo();
        int pageSize = adminSearchDoctorInputVo.getPageSize();
        adminSearchDoctorInputVo.setPageNo(pageNo);
        adminSearchDoctorInputVo.setPageSize(pageSize);
        pageNo = pageNo - 1 < 0 ? 0 : pageNo - 1;
        PageRequest pageRequest = PageRequest.of(pageNo, pageSize, Sort.Direction.DESC, "id");
        Specification<Doctor> specification = new Specification<Doctor>() {

            @Override
            public Predicate toPredicate(Root<Doctor> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> list = new ArrayList<Predicate>();
                // 创建时间-  开始
                if (!StringUtils.isEmpty(adminSearchDoctorInputVo.getBeginDate())) {
                    list.add(criteriaBuilder.greaterThan(root.get("createTime").as(String.class), adminSearchDoctorInputVo.getBeginDate()));
                }
                // 创建时间-  结束
                if (!StringUtils.isEmpty(adminSearchDoctorInputVo.getEndDate())) {
                    list.add(criteriaBuilder.lessThan(root.get("createTime").as(String.class), adminSearchDoctorInputVo.getEndDate()));
                }
                String phone = adminSearchDoctorInputVo.getPhone();
                if (!StringUtils.isEmpty(phone)) {
                    list.add(criteriaBuilder.equal(root.get("phone").as(String.class), phone));
                }
                String name = adminSearchDoctorInputVo.getDoctorName();
                if (!StringUtils.isEmpty(name)) {
                    list.add(criteriaBuilder.like(root.get("realName").as(String.class), name + "%"));
                }
                int gender = adminSearchDoctorInputVo.getGender();
                if (gender > 0) {
                    list.add(criteriaBuilder.equal(root.get("gender").as(Integer.class), gender));
                }
                int departmentId = adminSearchDoctorInputVo.getDepartmentId();
                if (departmentId > 0) {
                    list.add(criteriaBuilder.equal(root.get("department").as(Integer.class), departmentId));
                }
                int positionId = adminSearchDoctorInputVo.getPositionId();
                if (positionId > 0) {
                    list.add(criteriaBuilder.equal(root.get("position").as(Integer.class), positionId));
                }
                float price = adminSearchDoctorInputVo.getPrice();
                if (price > 0) {
                    list.add(criteriaBuilder.le(root.get("price").as(Float.class), price));
                }
                int jobYears = adminSearchDoctorInputVo.getJobYears();
                if (jobYears > 0) {
                    list.add(criteriaBuilder.le(root.get("jobYears").as(Integer.class), jobYears));
                }
                return criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
            }
        };
        List<DoctorOutputVo> doctorOutputVoList = Lists.newArrayList();
        Page<Doctor> pageData = doctorDao.findAll(specification, pageRequest);
        if (pageData.hasContent()) {
            List<Doctor> doctorList = pageData.getContent();
            for (Doctor d : doctorList) {
                DoctorOutputVo doctorOutputVo = new DoctorOutputVo();
                doctorOutputVo.setId(d.getId());
                doctorOutputVo.setPhone(d.getPhone());
                doctorOutputVo.setName(d.getRealName());
                doctorOutputVo.setGender(d.getGender());
                doctorOutputVo.setJobYears(d.getJobYears());
                doctorOutputVo.setDepartmentId(d.getDepartment());
                doctorOutputVo.setDepartmentName(d.getDepartmentName());
                doctorOutputVo.setPositionId(d.getPosition());
                doctorOutputVo.setPositionName(d.getPositionName());
                doctorOutputVo.setPrice(d.getPrice());
                doctorOutputVo.setCreateTime(DateFormatUtils.format(d.getCreateTime(), Constants.YYYY_MM_DD_HH_MM_SS));
                doctorOutputVo.setStatus(d.getCredentialStatus());
                doctorOutputVoList.add(doctorOutputVo);
            }
        }
        pageDataOutputVo.setTotalElement(pageData.getTotalElements());
        pageDataOutputVo.setTotalPageCount(pageData.getTotalPages());
        pageDataOutputVo.setPageData(doctorOutputVoList);

        return pageDataOutputVo;
    }
}
